Week3-Three-Tier-Architecture

Week 3: 3-Tier 아키텍처 (Web/WAS 분리)

Apache 웹 서버와 Tomcat WAS를 분리한 확장 가능한 3계층 아키텍처

Pasted image 20250909144049.png

아키텍처 개요

인터넷 사용자
    ↓ HTTP 요청
Internet Gateway
    ↓
VPC (10.0.0.0/16)
├── Public Subnet (10.0.1.0/24)
│   └── EC2 (Apache Web Server)
│       ├── 정적 파일 처리
│       ├── 프록시 서버
│       └── SSL 터미네이션
├── Private Subnet (10.0.2.0/24)
│   └── EC2 (Tomcat WAS)
│       ├── JSP/Servlet 처리
│       ├── 비즈니스 로직
│       └── 세션 관리
└── Private Subnet (10.0.3.0/24)
    └── RDS MySQL
        ├── 데이터 저장
        └── 트랜잭션 처리

상세 네트워크 아키텍처

VPC 설계 (확장)

VPC: webapp-vpc (10.0.0.0/16)
│
├── Internet Gateway: webapp-igw
│
├── Public Subnet: webapp-public-subnet
│   ├── CIDR: 10.0.1.0/24
│   ├── AZ: ap-northeast-2a
│   └── 용도: Web Server (Apache)
│
├── Private Subnet: webapp-private-subnet-app
│   ├── CIDR: 10.0.2.0/24
│   ├── AZ: ap-northeast-2a
│   └── 용도: WAS Server (Tomcat)
│
└── Private Subnet: webapp-private-subnet-db
    ├── CIDR: 10.0.3.0/24
    ├── AZ: ap-northeast-2a
    └── 용도: Database (RDS)

보안 그룹 설계

webapp-web-sg (Web Server):
├── HTTP (80) ← 0.0.0.0/0
├── HTTPS (443) ← 0.0.0.0/0  
├── SSH (22) ← My IP
└── Outbound: All

webapp-was-sg (WAS Server):
├── HTTP (8080) ← webapp-web-sg
├── AJP (8009) ← webapp-web-sg
├── SSH (22) ← webapp-web-sg
└── Outbound: All

webapp-db-sg (Database):
├── MySQL (3306) ← webapp-was-sg
└── Outbound: None

계층별 상세 구성

1. 웹 서버 계층 (Apache HTTP Server)

역할과 책임:

✅ 정적 콘텐츠 서비스 (HTML, CSS, JS, 이미지)
✅ SSL/TLS 터미네이션 및 보안
✅ 동적 요청을 WAS로 프록시
✅ 로드 밸런싱 (향후 다중 WAS 대비)
✅ 압축 및 캐싱

Apache 설정:

# /etc/httpd/conf/httpd.conf 주요 설정

DocumentRoot "/var/www/html/webapp"
DirectoryIndex index.html index.jsp

# 정적 파일 처리
<Directory "/var/www/html/webapp">
    Options -Indexes +FollowSymLinks
    AllowOverride None
    Require all granted
</Directory>

# JSP 파일을 Tomcat으로 프록시
ProxyPass /webapp/*.jsp http://10.0.2.x:8080/webapp/
ProxyPassReverse /webapp/*.jsp http://10.0.2.x:8080/webapp/

# 동적 경로를 Tomcat으로 프록시
ProxyPass /webapp/api/ http://10.0.2.x:8080/webapp/api/
ProxyPassReverse /webapp/api/ http://10.0.2.x:8080/webapp/api/

디렉토리 구조:

/var/www/html/webapp/
├── index.html (정적 메인 페이지)
├── css/
│   └── style.css
├── js/
│   └── app.js
├── images/
│   └── logo.png
└── api/ (프록시로 Tomcat 전달)

2. WAS 서버 계층 (Apache Tomcat)

역할과 책임:

✅ JSP/Servlet 실행 및 컴파일
✅ 세션 관리 및 상태 유지
✅ 데이터베이스 연결 풀 관리
✅ 비즈니스 로직 처리
✅ API 엔드포인트 제공

Tomcat 설정:

<!-- server.xml 주요 설정 -->
<Connector port="8080" protocol="HTTP/1.1"
           connectionTimeout="20000"
           redirectPort="8443" />

<Connector protocol="AJP/1.3"
           address="0.0.0.0"
           port="8009"
           redirectPort="8443" />

<Context path="/webapp" 
         docBase="/opt/tomcat/webapps/webapp"
         reloadable="true" />

웹 애플리케이션 구조:

/opt/tomcat/webapps/webapp/
├── WEB-INF/
│   ├── web.xml (배포 설정)
│   ├── lib/
│   │   └── mysql-connector-java.jar
│   └── classes/
│       └── Database.class
├── index.jsp (동적 메인 페이지)
├── users.jsp (사용자 관리)
├── api/
│   ├── users.jsp (REST API)
│   └── health.jsp (헬스체크)
└── META-INF/
    └── context.xml (DB 연결 설정)

요청 처리 흐름

정적 콘텐츠 요청

1. 사용자: GET /webapp/css/style.css
2. Apache: 로컬 파일 시스템에서 직접 서비스
3. 응답: CSS 파일 (캐시 헤더 포함)
   
처리 시간: ~10-50ms
부하: Web 서버만 관여, WAS/DB 무관

동적 콘텐츠 요청

1. 사용자: GET /webapp/users.jsp
2. Apache: JSP 요청 감지 → Tomcat으로 프록시
3. Tomcat: JSP 컴파일 및 실행
4. Database: 사용자 데이터 조회
5. Tomcat: HTML 생성 후 Apache로 응답
6. Apache: 클라이언트에게 최종 응답

처리 시간: ~100-500ms
부하: 모든 계층 관여

성능 최적화

Apache 최적화

# 압축 설정
LoadModule deflate_module modules/mod_deflate.so
<Location "/webapp">
    SetOutputFilter DEFLATE
    SetEnvIfNoCase Request_URI \
        \.(?:gif|jpe?g|png)$ no-gzip dont-vary
</Location>

# 캐싱 설정
LoadModule expires_module modules/mod_expires.so
<Directory "/var/www/html/webapp">
    ExpiresActive On
    ExpiresByType text/css "access plus 1 month"
    ExpiresByType application/javascript "access plus 1 month"
    ExpiresByType image/png "access plus 1 year"
</Directory>

Tomcat 최적화

# catalina.sh JVM 설정
export JAVA_OPTS="-Xms512m -Xmx1024m -XX:MetaspaceSize=256m"
export CATALINA_OPTS="-server -Djava.awt.headless=true"

# 연결 풀 최적화 (context.xml)
<Resource name="jdbc/webapp" 
          auth="Container"
          type="javax.sql.DataSource"
          maxActive="20"
          maxIdle="10"
          maxWait="10000"
          username="webapp_user"
          password="password"
          driverClassName="com.mysql.cj.jdbc.Driver"
          url="jdbc:mysql://rds-endpoint:3306/webapp_db"/>

데이터베이스 최적화

-- MySQL 설정 최적화
SET GLOBAL innodb_buffer_pool_size = 128M;
SET GLOBAL max_connections = 100;
SET GLOBAL query_cache_size = 32M;

-- 슬로우 쿼리 로그 활성화
SET GLOBAL slow_query_log = 1;
SET GLOBAL long_query_time = 2;

모니터링 및 로그

Apache 로그

# 액세스 로그
/var/log/httpd/access_log

# 에러 로그
/var/log/httpd/error_log

# 로그 포맷 (Combined Log Format)
%h %l %u %t "%r" %>s %O "%{Referer}i" "%{User-Agent}i"

Tomcat 로그

# 애플리케이션 로그
/opt/tomcat/logs/catalina.out

# 액세스 로그
/opt/tomcat/logs/localhost_access_log.txt

# 애플리케이션별 로그
/opt/tomcat/logs/webapp.log

보안 강화

Apache 보안 설정

# 서버 정보 숨김
ServerTokens Prod
ServerSignature Off

# 디렉토리 브라우징 비활성화
Options -Indexes

# 위험한 HTTP 메소드 차단
<LimitExcept GET POST HEAD>
    Require all denied
</LimitExcept>

# 보안 헤더 추가
Header always set X-Content-Type-Options nosniff
Header always set X-Frame-Options DENY
Header always set X-XSS-Protection "1; mode=block"

Tomcat 보안 설정

<!-- server.xml 보안 설정 -->
<Connector port="8080" protocol="HTTP/1.1"
           server="Apache"
           secure="true"
           maxPostSize="1048576" />

<!-- 관리 기능 비활성화 -->
<Host name="localhost" appBase="webapps"
      autoDeploy="false"
      deployOnStartup="false" />

성능 벤치마크

처리 능력 비교

Week 2 (Node.js 단일):
├── 동시 접속: ~100명
├── 응답 시간: 200-500ms
└── 처리량: ~100 req/sec

Week 3 (Web/WAS 분리):
├── 동시 접속: ~200-300명
├── 응답 시간: 150-400ms
├── 처리량: ~200 req/sec
└── 정적 파일: ~50ms (큰 개선)

리소스 사용량

Web 서버 (Apache):
├── CPU: 10-30%
├── 메모리: ~200MB
└── 주요 역할: 정적 파일, 프록시

WAS 서버 (Tomcat):
├── CPU: 20-60%
├── 메모리: ~600MB
└── 주요 역할: JSP 컴파일, 비즈니스 로직

장점과 개선점

Week 2 대비 개선점

✅ 역할 분담으로 성능 향상
├── 정적 파일: Apache가 직접 처리 (빠름)
└── 동적 파일: Tomcat이 전담 처리

✅ 확장성 향상
├── Web 서버와 WAS 독립적 확장 가능
└── 향후 다중 WAS 구성 기반 마련

✅ 보안 강화
├── WAS가 Private 서브넷에 격리
└── 계층별 세분화된 보안 그룹

✅ 유지보수성 향상
├── 각 계층별 독립적 관리
└── 장애 발생 시 영향 범위 최소화

여전한 한계점

❌ 단일 인스턴스 의존 (SPOF)
❌ 수동 확장 (Auto Scaling 없음)
❌ 고가용성 부족 (Single AZ)
❌ 로드 밸런싱 없음
❌ 장애 복구 자동화 없음

실제 운영 시나리오

정상 운영 시

사용자 요청 → Apache → 정적 파일 즉시 응답
사용자 요청 → Apache → Tomcat → DB → 응답

응답 시간: 평균 200ms
동시 처리: 200명
가용성: 99.5%

장애 시나리오

Web 서버 장애:
├── 전체 서비스 중단
└── 복구까지 서비스 불가

WAS 서버 장애:
├── 동적 페이지만 중단
├── 정적 파일은 계속 서비스
└── 수동 재시작 필요

DB 장애:
├── 전체 동적 기능 중단
└── RDS 자동 복구 대기

Week 3.5로의 발전 방향

해결해야 할 문제

1. 단일 장애점 (SPOF) 제거
   → Multi-AZ 구성

2. 자동 확장 구현
   → Auto Scaling Group

3. 트래픽 분산
   → Application Load Balancer

4. 고가용성 확보
   → Multi-AZ RDS

Week 3 완성: 확장 가능한 3-Tier 아키텍처 구축 완료
다음 단계: AWS EDU/Archive/조선대학교 AWS 멘토링/Edu Architecture/Week3.5-HA-Scalable-Architecture - 고가용성 및 자동 확장으로 업그레이드